home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / swtools / gencall / gencif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  4.7 KB  |  204 lines

  1. /*
  2.  * gencif.c
  3.  *                Gianni Mariani  3-Dec-1993
  4.  *
  5.  *  Generalized call interface
  6.  */
  7.  
  8. #include <alloca.h>
  9. #include "gencall.h"
  10.  
  11. /* ======== gcif_Prefunc ============================================== */
  12. /* PURPOSE:
  13.  *    To be used with CallFromGeneralArgs as the prep func.  It takes
  14.  *  the description of the arguments in GCIF_CALLDESC and generates
  15.  *  a call frame for the function call described therin.
  16.  *
  17.  * RETURNS:
  18.  *     Nothing
  19.  */
  20.  
  21. void    gcif_Prefunc(
  22.     char          * call_args,  /* Address of first arg to func    */
  23.     GCIF_CALLDESC     * args,        /* As passed in CallFromGeneralArgs    */
  24.     int                bytes,        /* As passed in CallFromGeneralArgs    */
  25.     unsigned          * p_flags     /* Pointer to the value "flags"    */
  26. ) {
  27.  
  28.     register GCIF_ARG * p_arg;        /* Pointer to arg descriptor    */
  29.     register void    ** p_argv;        /* Pointer to argvalue        */
  30.     register int    i;
  31.     register char     * argp;        /* Pointer to actual arg        */
  32.     register int    avn;
  33.     register int    tmp;
  34.  
  35.     tmp = 0;
  36.     argp = call_args;    
  37.     /* If the return type is a struct then                */
  38.     if ( args->gcif_rettype == gcif_struct ) {
  39.  
  40.     /* If the return type is a struct then the pointer to the    */
  41.     /* struct is the first arg                    */
  42.  
  43.     * ( void ** ) argp = args->gcif_retv;
  44.     argp += 4;
  45.     }
  46.  
  47.     /* go through all the args and insert them                */
  48.     avn = args->gcif_nargv;
  49.     p_argv = args->gcif_argv;
  50.  
  51.     for (
  52.     i = args->gcif_nargs, p_arg = args->gcif_args;
  53.     i && avn;
  54.     i --, p_arg ++
  55.     ) {
  56.     int        z;
  57.  
  58.     /* Do we need aligning                        */
  59.     if ( ( p_arg->gcif_align - 1 ) & ( unsigned ) argp ) {
  60.         argp = ( char * ) GCIF_ALIGN( argp, p_arg->gcif_align );
  61.     }
  62.  
  63.     if ( avn ) {
  64.         avn --;
  65.         if ( p_arg->gcif_type <= gcif_float ) {
  66.         * ( int * ) argp = * ( int * )( * p_argv );
  67.         z = 4;
  68.         } else if ( p_arg->gcif_type == gcif_double ) {
  69.         * ( double * ) argp = * ( double * )( * p_argv );
  70.         z = 8;
  71.         } else {
  72.         z = p_arg->gcif_size;
  73.         if ( z < 4 ) {
  74.             switch( p_arg->gcif_type ) {
  75.             case gcif_char :
  76.                 if ( 0 > ( char ) 0xff ) {
  77.                 * ( unsigned * ) argp = * ( char * ) ( * p_argv );
  78.                 } else {
  79.                 * ( signed * ) argp = * ( char * ) ( * p_argv );
  80.                 }
  81.                 break;
  82.             case gcif_uchar :
  83.                 * ( unsigned * ) argp = * ( gcif_uchar_t * ) ( * p_argv );
  84.                 break;
  85.             case gcif_schar :
  86.                 * ( signed * ) argp = * ( gcif_schar_t * ) ( * p_argv );
  87.                 break;
  88.             case gcif_ushort :
  89.                 * ( unsigned * ) argp = * ( gcif_ushort_t * ) ( * p_argv );
  90.                 break;
  91.             case gcif_sshort :
  92.                 * ( signed * ) argp = * ( gcif_sshort_t * ) ( * p_argv );
  93.                 break;
  94.             default:
  95.                 memcpy( argp, * p_argv, z );
  96.                 break;
  97.             }
  98.             z = 4;
  99.         } else {
  100.             memcpy( argp, * p_argv, z );
  101.         }
  102.         }
  103.         p_argv ++;
  104.         argp += z;
  105.     }
  106.     }
  107.  
  108.     return;
  109.  
  110. } /* end gcif_Prefunc */
  111.  
  112.  
  113. /* ======== gcif_call ================================================= */
  114. /* PURPOSE:
  115.  *    Call a function with arguments described in the call description
  116.  *  structure GCIF_CALLDESC. It also takes care of making a return
  117.  *  address for functions returning structures.
  118.  *
  119.  * RETURNS:
  120.  *     Whatever func returns if it is not returning a struct.
  121.  */
  122.  
  123. int gcif_call(
  124.     GCIF_FUNC_T          func,
  125.     GCIF_CALLDESC    * args
  126. ) {
  127.  
  128.     void        * retaddr;
  129.  
  130.     /* If the return value is a struct and we don't have a return    */
  131.     /* value address then we need to make one                */
  132.     if (
  133.     ( ! ( retaddr = args->gcif_retv ) )
  134.     && ( args->gcif_rettype == gcif_struct )
  135.     ) {
  136.     retaddr = alloca( args->gcif_retsize );
  137.     }
  138.  
  139.     return CallFromGeneralArgs(
  140.     gcif_Prefunc,
  141.     args,
  142.     args->gcif_bytes,
  143.     args->gcif_flags,
  144.     args->gcif_retv,
  145.     func
  146.     );
  147.  
  148. } /* end gcif_call */
  149.  
  150.  
  151. /* ======== gcif_filldesc ============================================= */
  152. /* PURPOSE:
  153.  *    Fill the call descriptor fields gcif_bytes and gcif_flags.
  154.  *
  155.  * RETURNS:
  156.  *     
  157.  */
  158.  
  159. void    gcif_filldesc(
  160.     GCIF_CALLDESC    * args
  161. ) {
  162.  
  163.     register unsigned      bytes = 0;
  164.     register int      i;
  165.     register GCIF_ARG    * p_arg;    /* Pointer to arg descriptor    */
  166.  
  167.     i = args->gcif_nargs;
  168.     p_arg = args->gcif_args;
  169.     if ( args->gcif_rettype == gcif_struct ) {
  170.     bytes = 4;
  171.     args->gcif_flags = GCIF_MKFLAGS(
  172.         args->gcif_rettype & ( RET_FP_MASK | RETINT ),
  173.         FP_PASS( gcif_void, gcif_void )
  174.     );
  175.     } else {
  176.     bytes = 0;
  177.     args->gcif_flags = GCIF_MKFLAGS(
  178.         args->gcif_rettype & ( RET_FP_MASK | RETINT ),
  179.         FP_PASS(
  180.         i>0 ? p_arg[ 0 ].gcif_type & RET_FP_MASK : gcif_void,
  181.         i>1 ? p_arg[ 1 ].gcif_type & RET_FP_MASK : gcif_void
  182.         )
  183.     );
  184.  
  185.     }
  186.     
  187.     /* Find the size required                        */
  188.     for ( ; i; i --, p_arg++) {
  189.     
  190.     if ( ( p_arg->gcif_align - 1 ) & bytes ) {
  191.         bytes = GCIF_ALIGN( bytes, p_arg->gcif_align );
  192.     }
  193.  
  194.     bytes += p_arg->gcif_size;
  195.     }
  196.  
  197.     args->gcif_bytes = bytes;
  198.     
  199.     return;
  200.  
  201. } /* end gcif_filldesc */
  202.  
  203.  
  204.